package com.siyoumi.app.sys.service.web_oauth;

import com.siyoumi.app.entity.WxUser;
import com.siyoumi.app.sys.entity.GetTokenData;
import com.siyoumi.app.sys.service.WxApiService;
import com.siyoumi.app.sys.vo.WebOauthCallBackData;
import com.siyoumi.app.sys.vo.WebOauthVo;
import com.siyoumi.app.sys.wx.WxOauthAppHandle;
import com.siyoumi.app.service.WxUserService;
import com.siyoumi.component.XBean;
import com.siyoumi.component.XJwt;
import com.siyoumi.component.XRedis;
import com.siyoumi.component.http.XHttpContext;
import com.siyoumi.config.SysConfig;
import com.siyoumi.entity.SysAccsuperConfig;
import com.siyoumi.exception.EnumSys;
import com.siyoumi.service.SysAccsuperConfigService;
import com.siyoumi.util.XDate;
import com.siyoumi.util.XReturn;
import com.siyoumi.util.XStr;
import com.siyoumi.validator.XValidator;
import lombok.extern.slf4j.Slf4j;

/**
 * 网页授权
 */
@Slf4j
public abstract class WebOauth {
    static public WebOauth getIns(String x) {
        SysAccsuperConfig entityConfig = SysAccsuperConfigService.getBean().getXConfig(x, true);
        WebOauth app = null;
        switch (entityConfig.getAconfig_type()) {
            case "wx":
                app = new WebOauthWx();
                break;
            case "wxapp":
                app = new WebOauthWxapp();
                break;
            default:
                XValidator.err(50031, "web oauth error, " + entityConfig.getAconfig_type());
        }
        return app;
    }

    /**
     * 调度模式
     *
     * @param vo
     */
    protected Boolean isDebug(WebOauthVo vo) {
        return "test".equals(vo.getCode());
    }

    static protected String getWebTokenKey(String s) {
        return "web_token:" + s;
    }

    public String getWebToken(String jwtToken) {
        XReturn r = XJwt.getBean().parseToken(jwtToken);
        XValidator.errWeb(r);

        //变短
        String webToken = XStr.md5(jwtToken);
        XRedis.getBean().setEx(getWebTokenKey(webToken), jwtToken, 5 * 60);
        return webToken;
    }

    /**
     * 获取数据 token_key
     *
     * @param webToken
     */
    static public XReturn getWebTokenData(String webToken) {
        if (XStr.isNullOrEmpty(webToken)) {
            return EnumSys.MISS_VAL.getR("miss web_token");
        }

        String jwtToken = "";
        if (SysConfig.getIns().isDev()) {
            jwtToken = XRedis.getBean().get(getWebTokenKey(webToken));
        } else {
            jwtToken = XRedis.getBean().getAndDel(getWebTokenKey(webToken));
        }
        if (XStr.isNullOrEmpty(jwtToken)) {
            return EnumSys.ERR_VAL.getR("web_token error");
        }

        XReturn r = XJwt.getBean().parseToken(jwtToken);
        String uid = r.getData("uid", "");
        String x = r.getData("x", "");
        String openid = r.getData("openid", "");

        GetTokenData data = GetTokenData.of(uid, x, openid);
        return WxApiService.getBean().loginReturnData(data);
    }

    /**
     * 授权链接
     *
     * @param data
     */
    protected String getCallbackUrl(WebOauthVo data) {
        StringBuilder urlCallback = new StringBuilder();
        urlCallback.append(SysConfig.getIns().getAppRoot());
        urlCallback.append("web/oauth_callback?1=1");
        if (XStr.hasAnyText(data.getApp_id())) {
            urlCallback.append("&app_id=" + data.getApp_id());
        }
        if (XStr.hasAnyText(data.getX())) {
            urlCallback.append("&x=" + data.getX());
        }
        if (XStr.hasAnyText(data.getScope())) {
            urlCallback.append("&scope=" + data.getScope());
        }
        if (XStr.hasAnyText(data.getKey())) {
            urlCallback.append("&key=" + data.getKey());
        }
        if (XStr.hasAnyText(data.getCode())) {
            urlCallback.append("&code=" + data.getCode());
        }
        if (XStr.hasAnyText(data.getTest_uid())) {
            urlCallback.append("&test_uid=" + data.getTest_uid());
        }

        String url = urlCallback.toString();
        log.debug("url_callback: {}", url);
        return url;
    }

    //re处理
    abstract public String reHandle(WebOauthVo data);

    abstract protected WebOauthCallBackData callbackHandleToken(WebOauthVo data);

    /**
     * 授权回调
     *
     * @param data
     */
    public String callbackHandle(WebOauthVo data) {
        WebOauthCallBackData callbackData;
        if (isDebug(data)) {
            XReturn tokenData = XReturn.getR(0);
            tokenData.setData("timestamp", XDate.toMs());
            tokenData.setData("x", data.getX());
            tokenData.setData("openid", data.getTest_uid());
            String jwtToken = WxApiService.getBean().getToken(tokenData);
            String webToken = getWebToken(jwtToken);

            callbackData = WebOauthCallBackData.getIns(data.getTest_uid(), webToken);
        } else {
            callbackData = callbackHandleToken(data);
        }


        //准备跳转
        String className = XStr.lineToHump(data.getApp_id());
        className = XStr.toUpperCase1(className + "Wx");
        String classPackage = XStr.concat("com.siyoumi.app.modules.", data.getApp_id(), ".service.", className);
        log.debug("className: {}", className);
        log.debug("classPackage: {}", classPackage);

        Class<?> clazz = null;
        try {
            clazz = Class.forName(classPackage);
        } catch (ClassNotFoundException ex) {
            log.error("未找到处理类");
        }
        if (clazz == null) {
            XValidator.err(20087, "应用未配置授权链接");
        }
        WxOauthAppHandle handle = (WxOauthAppHandle) XBean.newIns(clazz);

        String url = handle.appUrl(callbackData.getOpenid(), data);
        if (!url.contains("?")) {
            url += "?1=1";
        }
        url += "&token=" + callbackData.getWebToken();
        url += "&app_id=" + data.getApp_id();
        url += "&key=" + data.getKey();
        log.debug("url: {}", url);

        return url;
    }
}
